home *** CD-ROM | disk | FTP | other *** search
/ Nebula 1 / Nebula One.iso / Utilities / Converters / Convert_FONT / Source / FontConverter.m < prev    next >
Text File  |  1995-06-12  |  57KB  |  1,459 lines

  1. /***********************************************************************
  2. Converter class for Convert FONT which converts Mac fonts to NeXT fonts.
  3. Copyright (C) 1993 David John Burrowes
  4.  
  5. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 1, or (at your option) any later version.
  6.  
  7. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
  8.  
  9. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  10.  
  11. The author, David John Burrowes, can be reached at:
  12.     davidjohn@kira.net.netcom.com
  13.     David John Burrowes
  14.     1926 Ivy #10
  15.     San Mateo, CA 94403-1367
  16. ***********************************************************************/
  17.  
  18.  
  19. #import "FontConverter.h"
  20. #import "PSFile.h"
  21.  
  22. #import <architecture/byte_order.h>
  23.  
  24. #include <stdio.h>
  25. #include <string.h>
  26. #include <time.h>        // for ctime
  27.  
  28.  
  29. #define    VERSIONSTRING    "Convert FONT 1.1"
  30.  
  31. @implementation FontConverter
  32.  
  33. //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  34. //    Method:        init
  35. //    Parameters:    none
  36. //    Returns:     self
  37. //    Stores:        none
  38. //    Description:
  39. //        This initalizes the instance, of course, including mainly the initalization of
  40. //        the 256 entry array of names of the characters in the character set.  This is
  41. //        used when building both the .afm and the font.
  42. //    Bugs:
  43. //    History:
  44. //        93.01.10    djb    Added StoredName initialization.
  45. //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  46. - init
  47. {
  48.     Integer        index;
  49.  
  50.     [super init];
  51.     StoredName = NullCString;
  52.     EncodingVector[0] = "NUL";
  53.     EncodingVector[1] = "SOH";
  54.     EncodingVector[2] = "STX";
  55.     EncodingVector[3] = "ETX";
  56.     EncodingVector[4] = "EOT";
  57.     EncodingVector[5] = "ENQ";
  58.     EncodingVector[6] = "ACK";
  59.     EncodingVector[7] = "BEL";
  60.     EncodingVector[8] = "BS";
  61.     EncodingVector[9] = "HT";
  62.     EncodingVector[10] = "LF";
  63.     EncodingVector[11] = "VT";
  64.     EncodingVector[12] = "FF";
  65.     EncodingVector[13] = "CR";
  66.     EncodingVector[14] = "SO";
  67.     EncodingVector[15] = "SI";
  68.     EncodingVector[16] = "DLE";
  69.     EncodingVector[17] = "DC1";
  70.     EncodingVector[18] = "DC2";
  71.     EncodingVector[19] = "DC3";
  72.     EncodingVector[20] = "DC4";
  73.     EncodingVector[21] = "NAK";
  74.     EncodingVector[22] = "SYN";
  75.     EncodingVector[23] = "ETB";
  76.     EncodingVector[24] = "CAN";
  77.     EncodingVector[25] = "EM";
  78.     EncodingVector[26] = "SUB";
  79.     EncodingVector[27] = "ESC";
  80.     EncodingVector[28] = "FS";
  81.     EncodingVector[29] = "GS";
  82.     EncodingVector[30] = "RS";
  83.     EncodingVector[31] = "US";
  84.     EncodingVector[32] = "space";
  85.     EncodingVector[33] = "exclam";
  86.     EncodingVector[34] = "quotedbl";
  87.     EncodingVector[35] = "numbersign";
  88.     EncodingVector[36] = "dollar";
  89.     EncodingVector[37] = "percent";
  90.     EncodingVector[38] = "ampersand";
  91.     EncodingVector[39] = "quotesingle";
  92.     EncodingVector[40] = "parenleft";
  93.     EncodingVector[41] = "parenright";
  94.     EncodingVector[42] = "asterisk";
  95.     EncodingVector[43] = "plus";
  96.     EncodingVector[44] = "comma";
  97.     EncodingVector[45] = "hyphen";
  98.     EncodingVector[46] = "period";
  99.     EncodingVector[47] = "slash";
  100.     EncodingVector[48] = "zero";
  101.     EncodingVector[49] = "one";
  102.     EncodingVector[50] = "two";
  103.     EncodingVector[51] = "three";
  104.     EncodingVector[52] = "four";
  105.     EncodingVector[53] = "five";
  106.     EncodingVector[54] = "six";
  107.     EncodingVector[55] = "seven";
  108.     EncodingVector[56] = "eight";
  109.     EncodingVector[57] = "nine";
  110.     EncodingVector[58] = "colon";
  111.     EncodingVector[59] = "semicolon";
  112.     EncodingVector[60] = "less";
  113.     EncodingVector[61] = "equal";
  114.     EncodingVector[62] = "greater";
  115.     EncodingVector[63] = "question";
  116.     EncodingVector[64] = "at";
  117.     EncodingVector[65] = "A";
  118.     EncodingVector[66] = "B";
  119.     EncodingVector[67] = "C";
  120.     EncodingVector[68] = "D";
  121.     EncodingVector[69] = "E";
  122.     EncodingVector[70] = "F";
  123.     EncodingVector[71] = "G";
  124.     EncodingVector[72] = "H";
  125.     EncodingVector[73] = "I";
  126.     EncodingVector[74] = "J";
  127.     EncodingVector[75] = "K";
  128.     EncodingVector[76] = "L";
  129.     EncodingVector[77] = "M";
  130.     EncodingVector[78] = "N";
  131.     EncodingVector[79] = "O";
  132.     EncodingVector[80] = "P";
  133.     EncodingVector[81] = "Q";
  134.     EncodingVector[82] = "R";
  135.     EncodingVector[83] = "S";
  136.     EncodingVector[84] = "T";
  137.     EncodingVector[85] = "U";
  138.     EncodingVector[86] = "V";
  139.     EncodingVector[87] = "W";
  140.     EncodingVector[88] = "X";
  141.     EncodingVector[89] = "Y";
  142.     EncodingVector[90] = "Z";
  143.     EncodingVector[91] = "bracketleft";
  144.     EncodingVector[92] = "backslash";
  145.     EncodingVector[93] = "bracketright";
  146.     EncodingVector[94] = "asciicircum";
  147.     EncodingVector[95] = "underscore";
  148.     EncodingVector[96] = "grave";
  149.     EncodingVector[97] = "a";
  150.     EncodingVector[98] = "b";
  151.     EncodingVector[99] = "c";
  152.     EncodingVector[100] = "d";
  153.     EncodingVector[101] = "e";
  154.     EncodingVector[102] = "f";
  155.     EncodingVector[103] = "g";
  156.     EncodingVector[104] = "h";
  157.     EncodingVector[105] = "i";
  158.     EncodingVector[106] = "j";
  159.     EncodingVector[107] = "k";
  160.     EncodingVector[108] = "l";
  161.     EncodingVector[109] = "m";
  162.     EncodingVector[110] = "n";
  163.     EncodingVector[111] = "o";
  164.     EncodingVector[112] = "p";
  165.     EncodingVector[113] = "q";
  166.     EncodingVector[114] = "r";
  167.     EncodingVector[115] = "s";
  168.     EncodingVector[116] = "t";
  169.     EncodingVector[117] = "u";
  170.     EncodingVector[118] = "v";
  171.     EncodingVector[119] = "w";
  172.     EncodingVector[120] = "x";
  173.     EncodingVector[121] = "y";
  174.     EncodingVector[122] = "z";
  175.     EncodingVector[123] = "braceleft";
  176.     EncodingVector[124] = "bar";
  177.     EncodingVector[125] = "braceright";
  178.     EncodingVector[126] = "asciitilde";
  179.     EncodingVector[127] = "DEL";
  180.     EncodingVector[128] = "Adieresis";
  181.     EncodingVector[129] = "Aring";
  182.     EncodingVector[130] = "Ccedilla";
  183.     EncodingVector[131] = "Eacute";
  184.     EncodingVector[132] = "Ntilde";
  185.     EncodingVector[133] = "Odieresis";
  186.     EncodingVector[134] = "Udieresis";
  187.     EncodingVector[135] = "aacute";
  188.     EncodingVector[136] = "agrave";
  189.     EncodingVector[137] = "acircumflex";
  190.     EncodingVector[138] = "adieresis";
  191.     EncodingVector[139] = "atilde";
  192.     EncodingVector[140] = "aring";
  193.     EncodingVector[141] = "ccedilla";
  194.     EncodingVector[142] = "eacute";
  195.     EncodingVector[143] = "egrave";
  196.     EncodingVector[144] = "ecircumflex";
  197.     EncodingVector[145] = "edieresis";
  198.     EncodingVector[146] = "iacute";
  199.     EncodingVector[147] = "igrave";
  200.     EncodingVector[148] = "icircumflex";
  201.     EncodingVector[149] = "idieresis";
  202.     EncodingVector[150] = "ntilde";
  203.     EncodingVector[151] = "oacute";
  204.     EncodingVector[152] = "ograve";
  205.     EncodingVector[153] = "ocircumflex";
  206.     EncodingVector[154] = "odieresis";
  207.     EncodingVector[155] = "otilde";
  208.     EncodingVector[156] = "uacute";
  209.     EncodingVector[157] = "ugrave";
  210.     EncodingVector[158] = "ucircumflex";
  211.     EncodingVector[159] = "udieresis";
  212.     EncodingVector[160] = "dagger";
  213.     EncodingVector[161] = "degree";
  214.     EncodingVector[162] = "cent";
  215.     EncodingVector[163] = "sterling";
  216.     EncodingVector[164] = "section";
  217.     EncodingVector[165] = "bullet";
  218.     EncodingVector[166] = "paragraph";
  219.     EncodingVector[167] = "germandbls";
  220.     EncodingVector[168] = "registered";
  221.     EncodingVector[169] = "copyright";
  222.     EncodingVector[170] = "trademark";
  223.     EncodingVector[171] = "acute";
  224.     EncodingVector[172] = "dieresis";
  225.     EncodingVector[173] = "notequal";
  226.     EncodingVector[174] = "AE";
  227.     EncodingVector[175] = "Oslash";
  228.     EncodingVector[176] = "infinity";
  229.     EncodingVector[177] = "plusminus";
  230.     EncodingVector[178] = "lessequal";
  231.     EncodingVector[179] = "greaterequal";
  232.     EncodingVector[180] = "yen";
  233.     EncodingVector[181] = "mu";
  234.     EncodingVector[182] = "partialdiff";
  235.     EncodingVector[183] = "summation";
  236.     EncodingVector[184] = "product";
  237.     EncodingVector[185] = "pi";
  238.     EncodingVector[186] = "integral";
  239.     EncodingVector[187] = "ordfeminine";
  240.     EncodingVector[188] = "ordmasculine";
  241.     EncodingVector[189] = "Omega";
  242.     EncodingVector[190] = "ae";
  243.     EncodingVector[191] = "oslash";
  244.     EncodingVector[192] = "questiondown";
  245.     EncodingVector[193] = "exclamdown";
  246.     EncodingVector[194] = "logicalnot";
  247.     EncodingVector[195] = "radical";
  248.     EncodingVector[196] = "florin";
  249.     EncodingVector[197] = "approxequal";
  250.     EncodingVector[198] = "Delta";
  251.     EncodingVector[199] = "guillemotleft";
  252.     EncodingVector[200] = "guillemotright";
  253.     EncodingVector[201] = "ellipsis";
  254.     EncodingVector[202] = "nbspace";
  255.     EncodingVector[203] = "Agrave";
  256.     EncodingVector[204] = "Atilde";
  257.     EncodingVector[205] = "Otilde";
  258.     EncodingVector[206] = "OE";
  259.     EncodingVector[207] = "oe";
  260.     EncodingVector[208] = "endash";
  261.     EncodingVector[209] = "emdash";
  262.     EncodingVector[210] = "quotedblleft";
  263.     EncodingVector[211] = "quotedblright";
  264.     EncodingVector[212] = "quoteleft";
  265.     EncodingVector[213] = "quoteright";
  266.     EncodingVector[214] = "divide";
  267.     EncodingVector[215] = "lozenge";
  268.     EncodingVector[216] = "ydieresis";
  269.     EncodingVector[217] = "Ydieresis";
  270.     EncodingVector[218] = "fraction";
  271.     EncodingVector[219] = "currency";
  272.     EncodingVector[220] = "guilsinglleft";
  273.     EncodingVector[221] = "guilsinglright";
  274.     EncodingVector[222] = "fi";
  275.     EncodingVector[223] = "fl";
  276.     EncodingVector[224] = "daggerdbl";
  277.     EncodingVector[225] = "periodcentered";
  278.     EncodingVector[226] = "quotesinglbase";
  279.     EncodingVector[227] = "quotedblbase";
  280.     EncodingVector[228] = "perthousand";
  281.     EncodingVector[229] = "Acircumflex";
  282.     EncodingVector[230] = "Ecircumflex";
  283.     EncodingVector[231] = "Aacute";
  284.     EncodingVector[232] = "Edieresis";
  285.     EncodingVector[233] = "Egrave";
  286.     EncodingVector[234] = "Iacute";
  287.     EncodingVector[235] = "Icircumflex";
  288.     EncodingVector[236] = "Idieresis";
  289.     EncodingVector[237] = "Igrave";
  290.     EncodingVector[238] = "Oacute";
  291.     EncodingVector[239] = "Ocircumflex";
  292.     EncodingVector[240] = "apple";
  293.     EncodingVector[241] = "Ograve";
  294.     EncodingVector[242] = "Uacute";
  295.     EncodingVector[243] = "Ucircumflex";
  296.     EncodingVector[244] = "Ugrave";
  297.     EncodingVector[245] = "dotlessi";
  298.     EncodingVector[246] = "circumflex";
  299.     EncodingVector[247] = "tilde";
  300.     EncodingVector[248] = "macron";
  301.     EncodingVector[249] = "breve";
  302.     EncodingVector[250] = "dotaccent";
  303.     EncodingVector[251] = "ring";
  304.     EncodingVector[252] = "cedilla";
  305.     EncodingVector[253] = "hungarumlaut";
  306.     EncodingVector[254] = "ogonek";
  307.     EncodingVector[255] = "caron";
  308.     //
  309.     //    93.03.14    Added all code for NSEncodingVector support
  310.     //
  311.     //
  312.     //    Set up the NS encoding vector so that it uses the same names below 128.
  313.     //
  314.     for (index = 0; index < 128; index++)
  315.         NSEncodingVector[index] = EncodingVector[index];
  316.     //
  317.     //    Now, insert those strings for the NeXT encoding vector above 128.
  318.     //    If I had my act together, most of these could be set up as pointers to the
  319.     //    strings set up above.
  320.     //
  321.     NSEncodingVector[39] = "quoteright";
  322.     NSEncodingVector[96] = "quoteleft";
  323.     NSEncodingVector[128] = "figsep";
  324.     NSEncodingVector[129] = "Agrave";
  325.     NSEncodingVector[130] = "Aacute";
  326.     NSEncodingVector[131] = "Acircumflex";
  327.     NSEncodingVector[132] = "Atilde";
  328.     NSEncodingVector[133] = "Adieresis";
  329.     NSEncodingVector[134] = "Aring";
  330.     NSEncodingVector[135] = "Ccedilla";
  331.     NSEncodingVector[136] = "Egrave";
  332.     NSEncodingVector[137] = "Eacute";
  333.     NSEncodingVector[138] = "Ecircumflex";
  334.     NSEncodingVector[139] = "Edieresis";
  335.     NSEncodingVector[140] = "Igrave";
  336.     NSEncodingVector[141] = "Iacute";
  337.     NSEncodingVector[142] = "Icircumflex";
  338.     NSEncodingVector[143] = "Idieresis";
  339.     NSEncodingVector[144] = "Eth";
  340.     NSEncodingVector[145] = "Ntilde";
  341.     NSEncodingVector[146] = "Ograve";
  342.     NSEncodingVector[147] = "Oacute";
  343.     NSEncodingVector[148] = "Ocircumflex";
  344.     NSEncodingVector[149] = "Otilde";
  345.     NSEncodingVector[150] = "Odieresis";
  346.     NSEncodingVector[151] = "Ugrave";
  347.     NSEncodingVector[152] = "Uacute";
  348.     NSEncodingVector[153] = "Ucircumflex";
  349.     NSEncodingVector[154] = "Udieresis";
  350.     NSEncodingVector[155] = "Yacute";
  351.     NSEncodingVector[156] = "Thorn";
  352.     NSEncodingVector[157] = "mu";
  353.     NSEncodingVector[158] = "multiply";
  354.     NSEncodingVector[159] = "divide";
  355.     NSEncodingVector[160] = "copyright";
  356.     NSEncodingVector[161] = "exclamdown";
  357.     NSEncodingVector[162] = "cent";
  358.     NSEncodingVector[163] = "sterling";
  359.     NSEncodingVector[164] = "fraction";
  360.     NSEncodingVector[165] = "yen";
  361.     NSEncodingVector[166] = "florin";
  362.     NSEncodingVector[167] = "section";
  363.     NSEncodingVector[168] = "currency";
  364.     NSEncodingVector[169] = "quotesingle";
  365.     NSEncodingVector[170] = "quotedblleft";
  366.     NSEncodingVector[171] = "guillemotleft";
  367.     NSEncodingVector[172] = "guilsinglleft";
  368.     NSEncodingVector[173] = "guilsinglright";
  369.     NSEncodingVector[174] = "fi";
  370.     NSEncodingVector[175] = "fl";
  371.     NSEncodingVector[176] = "registered";
  372.     NSEncodingVector[177] = "endash";
  373.     NSEncodingVector[178] = "dagger";
  374.     NSEncodingVector[179] = "daggerdbl";
  375.     NSEncodingVector[180] = "periodcentered";
  376.     NSEncodingVector[181] = "brokenbar";
  377.     NSEncodingVector[182] = "paragraph";
  378.     NSEncodingVector[183] = "bullet";
  379.     NSEncodingVector[184] = "quotesinglbase";
  380.     NSEncodingVector[185] = "quotedblbase";
  381.     NSEncodingVector[186] = "quotedblright";
  382.     NSEncodingVector[187] = "guillemotright";
  383.     NSEncodingVector[188] = "ellipsis";
  384.     NSEncodingVector[189] = "perthousand";
  385.     NSEncodingVector[190] = "logicalnot";
  386.     NSEncodingVector[191] = "questiondown";
  387.     NSEncodingVector[192] = "onesuperior";
  388.     NSEncodingVector[193] = "grave";
  389.     NSEncodingVector[194] = "acute";
  390.     NSEncodingVector[195] = "circumflex";
  391.     NSEncodingVector[196] = "tilde";
  392.     NSEncodingVector[197] = "macron";
  393.     NSEncodingVector[198] = "breve";
  394.     NSEncodingVector[199] = "dotaccent";
  395.     NSEncodingVector[200] = "dieresis";
  396.     NSEncodingVector[201] = "twosuperior";
  397.     NSEncodingVector[202] = "ring";
  398.     NSEncodingVector[203] = "cedilla";
  399.     NSEncodingVector[204] = "threesuperior";
  400.     NSEncodingVector[205] = "hungarumlaut";
  401.     NSEncodingVector[206] = "ogonek";
  402.     NSEncodingVector[207] = "caron";
  403.     NSEncodingVector[208] = "emdash";
  404.     NSEncodingVector[209] = "plusminus";
  405.     NSEncodingVector[210] = "onequarter";
  406.     NSEncodingVector[211] = "onehalf";
  407.     NSEncodingVector[212] = "threequarters";
  408.     NSEncodingVector[213] = "agrave";
  409.     NSEncodingVector[214] = "aacute";
  410.     NSEncodingVector[215] = "acircumflex";
  411.     NSEncodingVector[216] = "atilde";
  412.     NSEncodingVector[217] = "adieresis";
  413.     NSEncodingVector[218] = "aring";
  414.     NSEncodingVector[219] = "ccedilla";
  415.     NSEncodingVector[220] = "egrave";
  416.     NSEncodingVector[221] = "eacute";
  417.     NSEncodingVector[222] = "ecircumflex";
  418.     NSEncodingVector[223] = "edieresis";
  419.     NSEncodingVector[224] = "igrave";
  420.     NSEncodingVector[225] = "AE";
  421.     NSEncodingVector[226] = "iacute";
  422.     NSEncodingVector[227] = "ordfeminine";
  423.     NSEncodingVector[228] = "icircumflex";
  424.     NSEncodingVector[229] = "idieresis";
  425.     NSEncodingVector[230] = "eth";
  426.     NSEncodingVector[231] = "ntilde";
  427.     NSEncodingVector[232] = "Lslash";
  428.     NSEncodingVector[233] = "Oslash";
  429.     NSEncodingVector[234] = "OE";
  430.     NSEncodingVector[235] = "ordmasculine";
  431.     NSEncodingVector[236] = "ograve";
  432.     NSEncodingVector[237] = "oacute";
  433.     NSEncodingVector[238] = "ocircumflex";
  434.     NSEncodingVector[239] = "otilde";
  435.     NSEncodingVector[240] = "odieresis";
  436.     NSEncodingVector[241] = "ae";
  437.     NSEncodingVector[242] = "ugrave";
  438.     NSEncodingVector[243] = "uacute";
  439.     NSEncodingVector[244] = "ucircumflex";
  440.     NSEncodingVector[245] = "dotlessi";
  441.     NSEncodingVector[246] = "udieresis";
  442.     NSEncodingVector[247] = "yacute";
  443.     NSEncodingVector[248] = "lslash";
  444.     NSEncodingVector[249] = "oslash";
  445.     NSEncodingVector[250] = "oe";
  446.     NSEncodingVector[251] = "germandbls";
  447.     NSEncodingVector[252] = "thorn";
  448.     NSEncodingVector[253] = "ydieresis";
  449.     NSEncodingVector[254] = "noddefined";
  450.     NSEncodingVector[255] = "asciicontrolchar";
  451.  
  452.     //
  453.     //    93.04.03    djb
  454.     //    Oh no!  Not another bloody array initalization!  What a WASTE!
  455.     //    Yep.
  456.     //    What the nasty thing for???
  457.     //    This allows us to convert a Mac character to a NeXT character.
  458.     //    But... What happened to your MacToNeXT converter object?
  459.     //    Good thought, but it doesn't do quotes the way I need. And, this is easier than a subclass..
  460.     //        I do'nt care THAT much anyway at this point.  Just wanna get it done.
  461.     //
  462.     //    (mac character names in ()'s, corresponding to the values in []'s
  463.     //
  464.     for (index = 0; index < 256; index++)
  465.         MacToNeXTLookup[index] = index;
  466.  
  467.     MacToNeXTLookup[0x11] = NullCharacter;    // (commandsymbol)
  468.     MacToNeXTLookup[0x12] = NullCharacter;    // (check)
  469.     MacToNeXTLookup[0x13] = NullCharacter;    // (diamond)
  470.     MacToNeXTLookup[0x14] = NullCharacter;    // (apple)
  471.  
  472.     MacToNeXTLookup[0x27] = 169;            // (quotesingle)
  473.     MacToNeXTLookup[0x60] = 193;            // (grave)
  474.  
  475.     MacToNeXTLookup[0x80] = 0x85;            // (Adieresis)
  476.     MacToNeXTLookup[0x81] = 0x86;            // (Aring)
  477.     MacToNeXTLookup[0x82] = 0x87;            // (Ccedilla)
  478.     MacToNeXTLookup[0x83] = 0x89;            // (Eacute)
  479.     MacToNeXTLookup[0x84] = 0x91;            // (Ntilde)
  480.     MacToNeXTLookup[0x85] = 0x96;            // (Odieresis)
  481.     MacToNeXTLookup[0x86] = 0x9A;            // (Udieresis)
  482.     MacToNeXTLookup[0x87] = 0xD6;            // (aacute)
  483.     MacToNeXTLookup[0x88] = 0xD5;            // (agrave)
  484.     MacToNeXTLookup[0x89] = 0xD7;            // (acircumflex)
  485.     MacToNeXTLookup[0x8A] = 0xD9;            // (adieresis)
  486.     MacToNeXTLookup[0x8B] = 0xD8;            // (atilde)
  487.     MacToNeXTLookup[0x8C] = 0xDA;            // (aring)
  488.     MacToNeXTLookup[0x8D] = 0xDB;            // (ccedilla)
  489.     MacToNeXTLookup[0x8E] = 0xDD;            // (eacute)
  490.     MacToNeXTLookup[0x8F] = 0xDC;            // (egrave)
  491.     //    0x9X
  492.     MacToNeXTLookup[0x90] = 0xDE;            // (ecircumflex)
  493.     MacToNeXTLookup[0x91] = 0xDF;            // (dieresis)
  494.     MacToNeXTLookup[0x92] = 0xE2;            // (iacute)
  495.     MacToNeXTLookup[0x93] = 0xE0;            // (igrave)
  496.     MacToNeXTLookup[0x94] = 0xE4;            // (icircumflex)
  497.     MacToNeXTLookup[0x95] = 0xE5;            // (idieresis)
  498.     MacToNeXTLookup[0x96] = 0xE7;            // (ntilde)
  499.     MacToNeXTLookup[0x97] = 0xED;            // (oacute)
  500.     MacToNeXTLookup[0x98] = 0xEC;            // (ograve)
  501.     MacToNeXTLookup[0x99] = 0xEE;            // (ocircumflex)
  502.     MacToNeXTLookup[0x9A] = 0xF0;            // (odieresis)
  503.     MacToNeXTLookup[0x9B] = 0xEF;            // (otilde)
  504.     MacToNeXTLookup[0x9C] = 0xF3;            // (uacute)
  505.     MacToNeXTLookup[0x9D] = 0xF2;            // (ugrave)
  506.     MacToNeXTLookup[0x9E] = 0xF4;            // (ucircumflex)
  507.     MacToNeXTLookup[0x9F] = 0xF6;            // (udieresis)
  508.     //    0xAX
  509.     MacToNeXTLookup[0xA0] = 0xB2;            // (dagger)
  510.     MacToNeXTLookup[0xA1] = NullCharacter;    // (degree)
  511.     MacToNeXTLookup[0xA2] = 0xA2;            // (cent)
  512.     MacToNeXTLookup[0xA3] = 0xA3;            // (sterling)
  513.     MacToNeXTLookup[0xA4] = 0xA7;            // (section)
  514.     MacToNeXTLookup[0xA5] = 0xB7;            // (bullet)
  515.     MacToNeXTLookup[0xA6] = 0xB6;            // (paragraph)
  516.     MacToNeXTLookup[0xA7] = 0xFB;            // (germandbls)
  517.     MacToNeXTLookup[0xA8] = 0xB0;            // (registerserif)
  518.     MacToNeXTLookup[0xA9] = 0xA0;            // (copyrightserif)
  519.     MacToNeXTLookup[0xAA] = NullCharacter;    // (trademarkserif)
  520.     MacToNeXTLookup[0xAB] = 0xC2;            // (acute)
  521.     MacToNeXTLookup[0xAC] = 0xC8;            // (dieresis)
  522.     MacToNeXTLookup[0xAD] = NullCharacter;    // (notequal)
  523.     MacToNeXTLookup[0xAE] = 0xE1;            // (AE)
  524.     MacToNeXTLookup[0xAF] = 0xE9;            // (Oslash)
  525.     //    0xBX
  526.     MacToNeXTLookup[0xB0] = NullCharacter;    //(infinity)
  527.     MacToNeXTLookup[0xB1] = 0xD1;            // (plusminus)
  528.     MacToNeXTLookup[0xB2] = NullCharacter;    // (lessequal)
  529.     MacToNeXTLookup[0xB3] = NullCharacter;    // (greaterequal)
  530.     MacToNeXTLookup[0xB4] = 0xA5;            // (yen)
  531.     MacToNeXTLookup[0xB5] = 0x9D;            // (mu)
  532.     MacToNeXTLookup[0xB6] = NullCharacter;    // (partialdiff)
  533.     MacToNeXTLookup[0xB7] = NullCharacter;    // (summation)
  534.     MacToNeXTLookup[0xB8] = NullCharacter;    // (product) 
  535.     MacToNeXTLookup[0xB9] = NullCharacter;    // (pi)
  536.     MacToNeXTLookup[0xBA] = NullCharacter;    // (integral)
  537.     MacToNeXTLookup[0xBB] = 0xE3;            // (ordfeminine)
  538.     MacToNeXTLookup[0xBC] = 0xEB;            // (ordmasculine)
  539.     MacToNeXTLookup[0xBD] = NullCharacter;    // (Omega)
  540.     MacToNeXTLookup[0xBE] = 0xF1;            // (ae)
  541.     MacToNeXTLookup[0xBF] = 0xF9;            // (oslash)
  542.     //    0xC0
  543.     MacToNeXTLookup[0xC0] = 0xBF;            // (questiondown)
  544.     MacToNeXTLookup[0xC1] = 0xA1;            // (exclamdown)
  545.     MacToNeXTLookup[0xC2] = 0xBE;            // (logicalnot)
  546.     MacToNeXTLookup[0xC3] = NullCharacter;    // (radical)
  547.     MacToNeXTLookup[0xC4] = 0xA6;            // (florin)
  548.     MacToNeXTLookup[0xC5] = NullCharacter;    // (approxequal)
  549.     MacToNeXTLookup[0xC6] = NullCharacter;    // (delta)
  550.     MacToNeXTLookup[0xC7] = 0xAB;            // (guillemotleft)
  551.     MacToNeXTLookup[0xC8] = 0xBB;            // (guillemotright)
  552.     MacToNeXTLookup[0xC9] = 0xBC;            // (elipsis)
  553.     MacToNeXTLookup[0xCA] = 0x80;            // (nbspace)   next calls it: (figsp)
  554.     MacToNeXTLookup[0xCB] = 0x81;            // (Agrave)
  555.     MacToNeXTLookup[0xCC] = 0x84;            // (Atilde)
  556.     MacToNeXTLookup[0xCD] = 0x95;            // (Otilde)
  557.     MacToNeXTLookup[0xCE] = 0xEA;            // (OE)
  558.     MacToNeXTLookup[0xCF] = 0xFA;            // (oe)
  559.     //    0xD0
  560.     MacToNeXTLookup[0xD0] = 0xB1;            // (endash)
  561.     MacToNeXTLookup[0xD1] = 0xD0;            // (emdash)
  562.     MacToNeXTLookup[0xD2] = 0xAA;            // (quotedblleft)
  563.     MacToNeXTLookup[0xD3] = 0xBA;            // (quotedblright)
  564.     MacToNeXTLookup[0xD4] = 0x60;            // (quoteleft)
  565.     MacToNeXTLookup[0xD5] = 0x27;            // (quoteright)
  566.     MacToNeXTLookup[0xD6] = 0x9F;            // (divide)
  567.     MacToNeXTLookup[0xD7] = NullCharacter;    // (lozenge)
  568.     MacToNeXTLookup[0xD8] = 0xFD;            // (ydieresis)
  569.     MacToNeXTLookup[0xD9] = NullCharacter;    // (Ydieresis)  (usually a picture in IM fonts)
  570.     MacToNeXTLookup[0xDA] = 0xA4;            // (fraction)
  571.     MacToNeXTLookup[0xDB] = 0xA8;            // (currency)
  572.     MacToNeXTLookup[0xDC] = 0xAC;            // (guilsinglleft)
  573.     MacToNeXTLookup[0xDD] = 0xAD;            // (guilsinglright)
  574.     MacToNeXTLookup[0xDE] = 0xAE;            // (fi)
  575.     MacToNeXTLookup[0xDF] = 0xAF;            // (fl)
  576.     //    0xE0
  577.     MacToNeXTLookup[0xE0] = 0xB3;            // (daggerdbl)
  578.     MacToNeXTLookup[0xE1] = 0xB4;            // (periodcentered)
  579.     MacToNeXTLookup[0xE2] = 0xB8;            // (quotesinglebase)
  580.     MacToNeXTLookup[0xE3] = 0xB9;            // (quotedblbase)
  581.     MacToNeXTLookup[0xE4] = 0xBD;            // (perthousand)
  582.     MacToNeXTLookup[0xE5] = 0x83;            // (Acircumflex)
  583.     MacToNeXTLookup[0xE6] = 0x8A;            // (Ecircumflex)
  584.     MacToNeXTLookup[0xE7] = 0x82;            // (Aacute)
  585.     MacToNeXTLookup[0xE8] = 0x8B;            // (Edieresis)
  586.     MacToNeXTLookup[0xE9] = 0x88;            // (Egrave)
  587.     MacToNeXTLookup[0xEA] = 0x8D;            // (Iacute)
  588.     MacToNeXTLookup[0xEB] = 0x8E;            // (Icircumflex)
  589.     MacToNeXTLookup[0xEC] = 0x8F;            // (Idieresis)
  590.     MacToNeXTLookup[0xED] = 0x8C;            // (Igrave)
  591.     MacToNeXTLookup[0xEE] = 0x93;            // (Oacute)
  592.     MacToNeXTLookup[0xEF] = 0x94;            // (Ocircumflex)
  593.     //    0xF0
  594.     MacToNeXTLookup[0xF0] = NullCharacter;    // (apple)
  595.     MacToNeXTLookup[0xF1] = 0x92;            // (Ograve)
  596.     MacToNeXTLookup[0xF2] = 0x98;            // (Uacute)
  597.     MacToNeXTLookup[0xF3] = 0x99;            // (Ucircumflex)
  598.     MacToNeXTLookup[0xF4] = 0x97;            // (Ugrave)
  599.     MacToNeXTLookup[0xF5] = 0xF5;            // (dotlessi)
  600.     MacToNeXTLookup[0xF6] = 0xC3;            // (circumflex)
  601.     MacToNeXTLookup[0xF7] = 0xC4;            // (tilde)
  602.     MacToNeXTLookup[0xF8] = 0xC5;            // (macron)
  603.     MacToNeXTLookup[0xF9] = 0xC6;            // (breve)
  604.     MacToNeXTLookup[0xFA] = 0xC7;            // (dotaccent)
  605.     MacToNeXTLookup[0xFB] = 0xCA;            // (ring)
  606.     MacToNeXTLookup[0xFC] = 0xCB;            // (cedilla)
  607.     MacToNeXTLookup[0xFD] = 0xCD;            // (hungarumlaut)
  608.     MacToNeXTLookup[0xFE] = 0xCE;            // (ogonek)
  609.     MacToNeXTLookup[0xFF] = 0xCF;            // (caron)
  610.  
  611.     //
  612.     //    Set the default of whether to use the NSEncoding to true
  613.     //
  614.     UseNSEncoding = YES;
  615.  
  616.     return self;
  617. }
  618.  
  619.  
  620. //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  621. //    Method:        free
  622. //    Parameters:    none
  623. //    Returns:     self
  624. //    Stores:        none
  625. //    Description:
  626. //        This free's the stored name if appropaite.  We don't free the encoding vector
  627. //        because it's all string constants.
  628. //    Bugs:
  629. //    History:
  630. //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  631. - free
  632. {
  633.     if (StoredName != NullCString)
  634.         FreeCString(StoredName);
  635.     return [super free];
  636. }
  637.  
  638.  
  639. //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  640. //    Method:        SetNSEncodingUse:
  641. //    Parameters:    A boolean flag
  642. //    Returns:     self
  643. //    Stores:        none
  644. //    Description:
  645. //        This quick hack of a routine allows the caller to specify whether this converter
  646. //        should use the NeXTSTEP or the Apple encoding vector.  YES means use NS,
  647. //        NO means use Apple.  Ideally, this should have a corresponding GetNSEncodingUse
  648. //        method, and perhaps this should take a string to allow for other vectors.  But, as
  649. //        indicated, this is only the code necessary to get the current job done.
  650. //    Bugs:
  651. //    History:
  652. //        93.03.14    djb    Created
  653. //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  654. - SetNSEncodingUse: (Boolean) NSEncodingFlag
  655. {
  656.     if (NSEncodingFlag == YES)
  657.         UseNSEncoding = YES;
  658.     else
  659.         UseNSEncoding = NO;
  660.  
  661.     return self;
  662. }
  663.  
  664.  
  665. //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  666. //    Method:        isThisAGoodFile
  667. //    Parameters:    A file instance
  668. //    Returns:     YES if the file is good, NO if it is not or if it is questionable.
  669. //    Stores:        the return value
  670. //                A descriptive string
  671. //    Description:
  672. //        This routine tries to judge if the specified file is a good one or not.  It then
  673. //        returns a string in storage and returns a result.
  674. //        the first 16 bits of a font define what kinda font it is.  We look for the two types
  675. //        that I've worked with, and hope that what we have is indeed a font.  note that
  676. //        the bit flags of those 2 bytes are defined as follows by apple:
  677. //            boolean = 1;                    /* Reserved */
  678. //            boolean        doExpandFont, dontExpandFont;
  679. //            boolean        proportionalFont, fixedWidthFont;
  680. //            boolean = 1;                    /* Reserved */
  681. //            unsigned bitstring[2] = 0;        /* Reserved */
  682. //            boolean        blackFont, colorFont;
  683. //            boolean        notSynthetic, isSynthetic;
  684. //            boolean        nofctbRsrc, hasfctbRsrc;
  685. //            unsigned bitstring[3] = 0;        /* Reserved */
  686. //            unsigned bitstring[2]    oneBit, twoBit, fourBit, eightBit;
  687. //                                        /* Font depth */
  688. //            boolean        noCharWidthTable, hasCharWidthTable;
  689. //            boolean        noImageHeightTable, hasImageHeightTable;
  690. //    Bugs:
  691. //        Actually, the last two bit fields don't matter at all, in that one can ignore them
  692. //        safely (and I do).  it might be nice to improve the program at a later date so it
  693. //        maintains the extra width info...
  694. //        On further reflection, it would make a LOT more sense to read in the whole
  695. //        font structure, and then assure that there are a positive number of characters,
  696. //        that the asent is positive , nDescent negative or zero, etc.  In addtion to what
  697. //        we're already doing.
  698. //    History
  699. //        93.01.09    djb    oops.  Was freeing buffer after had put it into the second result, which
  700. //                    meant sometimes freeing it before it could be used.
  701. //        93.08.01    djb    Added NXSwap... call to hide endian issues...
  702. //        93.08.15    djb    Argh!  I need to be casting the results!!!
  703. //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  704. - (Boolean) isThisAGoodFile: theFile
  705. {
  706.     FilePos            location    = 0;
  707.     bits16            fontType;
  708.     CString            buffer;
  709.     Boolean            result    = NO;
  710.     //
  711.     //    First, get the integer that defines the type of font we are working with...
  712.     //    (this is the best identifier we can get from the font data structure)
  713.     //
  714.     location = [theFile GetCurrentPosition];
  715.     [theFile   MoveTo: 0];
  716.     [theFile   Read: 2 BytesInto: (ByteString) &fontType];
  717.     fontType = (INTEGER) NXSwapBigShortToHost(fontType);
  718.     [theFile   MoveTo: location];
  719.     //
  720.     //    with the font type in hand, return the proper values...
  721.     //
  722.     switch (fontType)
  723.     {
  724.         case 0x9000 :
  725.         case 0xB000 :
  726.             result = YES;
  727.             break;
  728.         case 0x9001:
  729.         case 0xB001:
  730.             [self  PutCString: "This font has a `height table\', which  Convert FONT can not convert.  You can probably convert the font safely, but the converted heights may be wrong." Into: SECOND_RESULT];
  731.             result = NO;
  732.             break;
  733.         case 0x9002:
  734.         case 0xB002:
  735.             [self  PutCString: "This font has a `width table\', Convert FONT can not convert.  You can probably convert the font safely, but the converted widths may be wrong." Into: SECOND_RESULT];
  736.             result = NO;
  737.             break;
  738.         case 0x9003:
  739.         case 0xB003:
  740.             [self  PutCString: "This font has both a `width\' and a `height\' table, which Convert FONT can not convert.  You can probably convert the font safely, but the character dimensions may be wrong." Into: SECOND_RESULT];
  741.             result = NO;
  742.             break;
  743.         default:
  744.             buffer = NewCString(127);
  745.             //    93.01.24    djb    Compiler doesn't like the %2x and fontType.  Not sure why.
  746.             //                I tried a 0x2324 as a param, and it didn't like that either.
  747.             sprintf(buffer, "This may not be a convertable font.  Proceed with caution.  If you are sure this is a good font, and it fails to convert, give the author this: (%2X)", (unsigned int) fontType);
  748.             [self  PutCString: buffer Into: SECOND_RESULT];
  749.             result = NO;
  750.             break;
  751.     }
  752.  
  753.     return result;
  754. }
  755.  
  756.  
  757. //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  758. //    Method:        Copy:BitsAtOffset:From:Into:
  759. //    Parameters:    The number of bits in the source data to be copied
  760. //                The number of bits, offset from the start of source, where source data starts
  761. //                The source byte string to copy from
  762. //                The destination byte string to copy into
  763. //    Returns:     The destination pointer (identical to the one passed)
  764. //    Stores:        error code
  765. //                1 The destination pointer (as a Pointer)
  766. //                2 The count of the number of bytes stored in the destination
  767. //    Description:
  768. //        This routine can be used to extract arbitrary bit patterns out of a source string.
  769. //        It was created to serve two different purposes: to allow one to get a bitmap from
  770. //        a PICT image so it was left justified in its storage space, rather than offset some
  771. //        number of bits in.  The other use was to extract the characters of a Mac font,
  772. //        one scanline at a time, from the single bitmap tht makes up a Mac font.
  773. //        Ultimately, the work is simple: take a source string, and an offset into it where
  774. //        the data resides (and the length of the source data).  Copy the relevant bits from
  775. //        the source to the dest.  Note that this aligns the left of the source data to the
  776. //        beginning of a byte boundrary in dest.  Also note that it fills up an integral number
  777. //        of bytes in dest, filling the last out with 0's if needed.
  778. //    Bugs:
  779. //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  780. - (ByteString) Copy: (PositiveInteger) sourceSize
  781.     BitsAtOffset: (PositiveInteger) offset
  782.     From: (ByteString) source
  783.     Into: (ByteString) dest
  784. {
  785.     PositiveInteger    firstByte, lastByte;    // First and last bytes in source string to be copied
  786.     PositiveInteger    index, destIndex;        // indices into source and dest strings
  787.     PositiveInteger    offsetInByte;            // Number of bits into a byte a dest byte starts
  788.     Byte            byte1, byte2;            // Temporary bytes to hold info as copied
  789.     
  790.     Byte    mask;
  791.     PositiveInteger    bitpos, bitsMoved, finalBits;
  792.     
  793.     [self    ResetResults];
  794.     
  795.     if (sourceSize == 0)
  796.     {
  797.         [self   StoreErrorCode: ERR_BADSOURCESIZE
  798.             AndText: "You requested for 0 bytes.  This has been fulfilled, weird as it is."];
  799.         dest[0] = 0;
  800.         [self   StorePointer: (Pointer) dest];
  801.         [self   PutPositiveInteger: 0 Into: SECOND_RESULT];
  802.     }
  803.     else
  804.     {
  805.         //
  806.         //    Computer our start and end position in source string, in bytes, and compute what
  807.         //    bit offset in the first byte we should start working at
  808.         //
  809.         firstByte = offset / 8;
  810.         lastByte = ((offset+sourceSize-1) / 8);
  811.         offsetInByte = offset % 8;    // Zero origin...
  812.         //
  813.         //    Bear in mind that it's most likely that the destination byte will straddle two bytes
  814.         //    in the source string.  So.  Get two bytes at a time from the source, and bitshift
  815.         //    so they each contain only the bits that are relevant to the destination byte (get its
  816.         //    upper and lower parts), then fuse the two parts together into a single destination
  817.         //    byte.  Increment our destination index, and store the upper of the two bytes, for
  818.         //    it will be the lower one the next time around. 
  819.         //    Following this, deal with any remaining bits that might belong to the final
  820.         //    dest byte, and pad them with zero.
  821.         //
  822.         destIndex = 0;
  823.         //
  824.         //    Two major cases: our data resides in only a single byte, or it spans
  825.         //    two or more bytes:
  826.         //
  827.         if (firstByte == lastByte)
  828.         {
  829.             //
  830.             //    First, shift the data in the byte down so it is aligned with the start
  831.             //    of the byte.
  832.             //    Then Build a mask to clear out any extraneous bits that were above the
  833.             //    source data.  We're too lazy to actully determine whether there is any
  834.             //    junk (there would be if the offset to the data + the length < 8 bits), and
  835.             //    so, build a mask of sourceSize length, and use it.
  836.             //
  837.             byte1 = source[firstByte] << offsetInByte;
  838.             mask = 0x00;
  839.             for (bitpos = 0; bitpos < sourceSize; bitpos ++)
  840.             {
  841.                 mask = mask >> 1;
  842.                 mask |= 0x80;
  843.             }
  844.             dest[destIndex] = byte1 &  mask;
  845.             destIndex++;
  846.         }
  847.         else
  848.         {
  849.             //
  850.             //    Start off by pulling off contiguous groups of 8 bits from
  851.             //    the source, and storing them as bytes in the destination.
  852.             //
  853.             for (index = firstByte; index < lastByte; index++)
  854.             {
  855.                 byte1 = source[index] << offsetInByte;
  856.                 byte2 = source[index+1] >> ( 8 - offsetInByte);
  857.                 
  858.                 dest[destIndex] = byte1 | byte2;
  859.                 destIndex++;
  860.             }
  861.             //
  862.             //    There are 3 possible states at this point:
  863.             //    - We happen to have copied exactly the number of source bits to the dest.
  864.             //    - We have copied too many bits to the dest (i.e. our final byte2 group had
  865.             //        too many source bits in it)
  866.             //    - We have not copied enough bits (i.e. there were bits in source[lastByte] that
  867.             //        were not moved with those in byte2).
  868.             //    Process each of these accordingly.
  869.             //
  870.             //    Calculate:
  871.             //        Bits copied to dest in byte2:
  872.             //        Bits source bits actually in source[lastbyte]
  873.             //
  874.             bitsMoved = offsetInByte;
  875.             finalBits = (offset+sourceSize) - (lastByte*8);
  876.             //
  877.             //    There are a few bits which we have not yet moved.
  878.             //
  879.             if (finalBits > bitsMoved)
  880.             {
  881.                 byte1 = source[index] << bitsMoved;
  882.                 mask = 0x00;
  883.                 for (bitpos = 0; bitpos < (finalBits - bitsMoved); bitpos ++)
  884.                 {
  885.                     mask = mask >> 1;
  886.                     mask |= 0x80;
  887.                 }
  888.                 dest[destIndex] = byte1 & mask;
  889.                 destIndex++;
  890.             }
  891.             //
  892.             //    Check if we moved more bits than we should have
  893.             //
  894.             else  if (finalBits < bitsMoved)
  895.             {
  896.                 mask = 0x00;
  897.                 for (bitpos = 0; bitpos < finalBits+( 8 - offsetInByte); bitpos ++)
  898.                 {
  899.                     mask = mask >> 1;
  900.                     mask |= 0x80;
  901.                 }
  902.                 dest[destIndex-1] = dest[destIndex-1] & mask;
  903.             }
  904.         }
  905.     
  906.         [self   StoreErrorCode: ERR_OK AndText: "No errors (big surprise)"];
  907.         [self   StorePointer: (Pointer) dest];
  908.         [self   PutPositiveInteger: destIndex Into: SECOND_RESULT];
  909.     }
  910.  
  911.     return dest;
  912. }
  913.  
  914.  
  915.  
  916. //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  917. //    Method:        BuildAFMFileFrom:Into:
  918. //    Parameters:    A Mac font record that we should build an afm file based on
  919. //                a text file instance that has already been created and opened to put
  920. //                    the AFM file information into
  921. //    Returns:     self
  922. //    Stores:        ?????
  923. //    Description:
  924. //    Bugs:
  925. //        For the capheight, xheight, ascender and descender values, we use the
  926. //        simple absolute height and depth of the font box to fill these in.  If we were
  927. //        a bit more adventurous, we could extract the bitmap information for the
  928. //        relevant H, x d and p characters, by examining when we cease getting
  929. //        blank lines back from the bit extractor.
  930. //        Feeling really adventurous, we could provide real bounding boxes for all
  931. //        characters, as justdescribed.  I think this ia version 2 feature.
  932. //    History:
  933. //        93.01.24    djb    Oddly, nDescent is sometimes the negative of the ascent!!  descent
  934. //                    always seems good, so replacing the one with the other.
  935. //        93.04.03    djb    Modified so that when converting to a NeXTSTEP encoding, it will convert to
  936. //                        the proper characters above 128.
  937. //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  938. - BuildAFMFileFrom: (FontRecPtr) macFont Into: afmFile
  939. {
  940.     CString        fontName;
  941.     Integer     thechar,
  942.                 index,
  943.                 numChars;
  944.     OWEntry    *OffsetWidthTable;
  945.     CString        buffer             = NewCString(1024);
  946.      Real            conversionFactor    =  (1.0/macFont->fRectHeight) * 1000;
  947.     CString        theName;        // Used to point to a constant string to be written ou.
  948.     Boolean        characterUsed[255];
  949.     Character        macCharacterFor[255];
  950.     Character    NeXTCharacter;
  951.     
  952.     [self    ResetResults];
  953.  
  954.     for (index = 0; index < 256; index++)
  955.     {
  956.         characterUsed[index] = NO;
  957.         macCharacterFor[index] = NullCharacter;
  958.     }
  959.  
  960.     fontName = [afmFile    GetBasename];
  961.     
  962.     OffsetWidthTable = (OWEntry*)  (&(macFont->owTLoc) + macFont->owTLoc);
  963.  
  964.     [afmFile   WriteTextLine: "StartFontMetrics 1.0"];
  965.     [afmFile   WriteTextLine: "Version 1.0"];
  966.     [afmFile   WriteTextUsing: buffer
  967.             WithFormat: "Comment (Converted from Macintosh bitmap font using %s)\n",
  968.             VERSIONSTRING];
  969.     [afmFile   WriteTextUsing: buffer WithFormat: "FontName %s\n", fontName];
  970.     [afmFile   WriteTextUsing: buffer WithFormat: "FullName %s\n", StoredName];
  971.     [afmFile   WriteTextUsing: buffer WithFormat: "FamilyName %s\n", StoredName];
  972.     [afmFile   WriteTextLine: "Weight Roman"];
  973.     [afmFile   WriteTextLine: "ItalicAngle 0"];
  974.     if  ((macFont->fontType & fixedFont) == fixedFont)
  975.         [afmFile   WriteTextLine: "IsFixedPitch true"];  
  976.     else
  977.         [afmFile   WriteTextLine: "IsFixedPitch false"];  
  978.     [afmFile   WriteTextUsing: buffer  WithFormat: "FontBBox 0 %.3f %.3f %.3f\n",
  979.                 (-1*macFont->descent) * conversionFactor,
  980.                 macFont->fRectWidth * conversionFactor,
  981.                 macFont->ascent * conversionFactor];
  982.     //
  983.     //    Added code for NS Encoding.
  984.     //
  985.     if (UseNSEncoding == YES)
  986.         [afmFile   WriteTextLine: "EncodingScheme AdobeStandardEncoding"];
  987.     else
  988.         [afmFile   WriteTextLine: "EncodingScheme FontSpecific"];
  989.  
  990.     [afmFile   WriteTextLine: "UnderlinePosition -180"];  // A rash assumption
  991.     [afmFile   WriteTextLine: "UnderlineThickness 10"];  // Ditto
  992.     //
  993.     //    Note that we could actually be computing the following for real, relatively easily.. 
  994.     //
  995.     [afmFile   WriteTextLine: "CapHeight 1000"];
  996.     [afmFile   WriteTextLine: "XHeight 1000"];
  997.     [afmFile   WriteTextLine: "Ascender 1000"];
  998.     [afmFile   WriteTextUsing: buffer  WithFormat: "Descender %.3f\n",
  999.                 (macFont->descent * -1) * conversionFactor];
  1000.     //
  1001.     //    Count the number of characters that actually exist inthe font (except null char)
  1002.     //
  1003.     numChars = 0;
  1004.     for (thechar = macFont->firstChar; thechar <= macFont->lastChar;  thechar++)
  1005.     {
  1006.         index = thechar -  macFont->firstChar;
  1007.         if ( ( OffsetWidthTable[index].offset != -1) && ( OffsetWidthTable[index].width != -1))
  1008.             numChars += 1;
  1009.     }
  1010.     //
  1011.     //    Now, start writing out the character metrics
  1012.     //    NOTE:  This loop produces one of two results.  If we are using a Mac endocing, it writes out
  1013.     //    the metrics to the file.  If we are doing the NeXTSTEP encoding, then we just record which
  1014.     //    characters are used, and later write out the metrics.  This is done because if mac character N
  1015.     //    was used, then we want to write out the encoding for the NeXT character M.  That is, the Mac bullet
  1016.     //    might be at M, but it would be at M on the NeXT.  Since it is possible that M < N this would mean
  1017.     //    that we'd have to either write out the metrics in an unordered fashion, or not write out the values
  1018.     //    at all.  The solution is to record an array of which characters were used, and then write
  1019.     //    out metrics based on these later.
  1020.     //    Note that we also do not write out the StartCharMetrics line if we are doing NeXTstep encoding.
  1021.     //    This is because the number of characters may be smaller (some of the mac chars available will
  1022.     //    map to nothing in the nextstep endocing, and thus effectively vanish.  Sigh.
  1023.     //
  1024.     if (UseNSEncoding == NO)
  1025.         [afmFile   WriteTextUsing: buffer  WithFormat: "StartCharMetrics %d\n", numChars];
  1026.     else
  1027.         numChars = 0;
  1028.         
  1029.     for (thechar = macFont->firstChar; thechar <= macFont->lastChar;  thechar++)
  1030.     {
  1031.         index = thechar -  macFont->firstChar;
  1032.         if ( ( OffsetWidthTable[index].offset != -1) && ( OffsetWidthTable[index].width != -1))
  1033.         {
  1034.             //
  1035.             //    93.03.14    Added NS Encoding support.
  1036.             //    93.04.03    Modified because was producing improper names above 128, it seems.
  1037.             //
  1038.             if (UseNSEncoding == YES)
  1039.             {
  1040.                 NeXTCharacter = MacToNeXTLookup[thechar];
  1041.                 if (NeXTCharacter != NullCharacter)
  1042.                 {
  1043.                     //
  1044.                     //    The following should really be using a struct.  yuck.
  1045.                     //
  1046.                     characterUsed[NeXTCharacter] = YES;
  1047.                     macCharacterFor[NeXTCharacter] = thechar;
  1048.                     numChars++;
  1049.                 }
  1050.             }
  1051.             else
  1052.             {
  1053.                 theName = EncodingVector[thechar];
  1054.             
  1055.                 [afmFile   WriteTextUsing: buffer 
  1056.                     WithFormat: "C %d ; WX %.3f ; N %s ; B %.3f %.3f %.3f %.3f ;\n",
  1057.                         thechar,  OffsetWidthTable[index].width* conversionFactor,
  1058.                         theName,
  1059.                         (macFont->kernMax + OffsetWidthTable[index].offset)
  1060.                             * conversionFactor,
  1061.                         (macFont->descent * -1) * conversionFactor,
  1062.                         (OffsetWidthTable[index].width* conversionFactor),
  1063.                         macFont->ascent * conversionFactor];
  1064.             }
  1065.         }
  1066.     }
  1067.     //
  1068.     //    93.04.03    djb    Now, if we used the NS encoding, we should write out the values now that
  1069.     //                    we know which characters were used.
  1070.     //
  1071.     if (UseNSEncoding == YES)
  1072.     {
  1073.         [afmFile   WriteTextUsing: buffer  WithFormat: "StartCharMetrics %d\n", numChars];
  1074.         for (thechar = 0; thechar < 256; thechar++)
  1075.         {
  1076.             if ( characterUsed[thechar] == YES)
  1077.             {
  1078.                 index = macCharacterFor[thechar] -  macFont->firstChar;
  1079.                 [afmFile   WriteTextUsing: buffer 
  1080.                     WithFormat: "C %d ; WX %.3f ; N %s ; B %.3f %.3f %.3f %.3f ;\n",
  1081.                         thechar,  OffsetWidthTable[index].width* conversionFactor,
  1082.                         NSEncodingVector[thechar],
  1083.                         (macFont->kernMax + OffsetWidthTable[index].offset)
  1084.                             * conversionFactor,
  1085.                         (macFont->descent * -1) * conversionFactor,
  1086.                         (OffsetWidthTable[index].width* conversionFactor),
  1087.                         macFont->ascent * conversionFactor];
  1088.             }
  1089.         }
  1090.     }
  1091.  
  1092.     [afmFile   WriteTextLine: "EndCharMetrics"];
  1093.     [afmFile   WriteTextLine: "EndFontMetrics"];
  1094.     FreeCString(buffer);
  1095.     return self;
  1096. }
  1097.  
  1098.  
  1099.  
  1100. //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  1101. //    Method:        ConvertMacFONT:ToType3Font:
  1102. //    Parameters:    The file to read a Mac front from
  1103. //                The file to write a Type 3 font to.
  1104. //    Returns:     a 16 bit Mac INTEGER (signed!)
  1105. //    Stores:        ?????
  1106. //    Description:
  1107. //        A note about the character coordinates is in order here.  the main font imaging
  1108. //        routine (the postscript proc: BuldGlyph) had requent references to the height
  1109. //        of the font.  don't be misled!  Notice that all of them, by the time they are
  1110. //        executed are basically turned into relative measures (numbers from 0 to 1
  1111. //        usually).  It has taken me a while to grasp what was going on here.  I suppose
  1112. //        if I'd gone with adobe's recommendation of using a 1000 by 1000 coordinate
  1113. //        system , it might have been easier.  But I didn't want to completely obscure
  1114. //        the numbers that the mac form had.  Using such a coord system woulda given
  1115. //        lotsa xxx.yyyy numbers, and it would not have been as clear.  Anyway.
  1116. //        You needn't agree. It's just what I chose to do then.  Not sure I'd do it again.
  1117. //    Bugs:
  1118. //        We rely on the fact that the destination file name happens to be the name that
  1119. //        we want to have for the font...
  1120. //    History:
  1121. //        93.01.24    djb    Oddly, nDescent is sometimes the negative of the ascent!!  descent
  1122. //                    always seems good, so replacing the one with the other.
  1123. //        93.08.01    djb    Replaced code to read in the font record with a call to the GetFontRec...
  1124. //                    method, so all endianness of i/o is hidden from the app.
  1125. //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  1126. - ConvertMacFONT: SourceFile ToType3Font: DestFile AndAFM: afmFile
  1127. {
  1128.     FontRecPtr    fontPtr;
  1129.     PositiveInteger    fontLength;
  1130.     CString        tempString = NewCString(1024);
  1131.     Integer     thechar, index;
  1132.     INTEGER    *LocationTable;
  1133.     OWEntry    *OffsetWidthTable;
  1134.     ByteString    FontImage, RasterLine, destLine;
  1135.     INTEGER    FontHeight, RowWords;
  1136.     PositiveInteger    startBit, endBit, line;
  1137.     PositiveInteger    imageWidth;
  1138.     CString            buffer = NewCString(1024); 
  1139.     time_t            currentTime = time(0);
  1140.     CString            fontName;
  1141.     CString            timeString;
  1142.      Real                conversionFactor;
  1143.  
  1144.     fontName = [DestFile    GetBasename];
  1145.     //
  1146.     //    Read in the font to use
  1147.     //
  1148.     fontLength = [SourceFile  FileSize];
  1149.     fontPtr = [self   GetFontRecordWithLength: fontLength  From: SourceFile];
  1150.     conversionFactor =  (1.0/fontPtr->fRectHeight) * 1000;
  1151.     //
  1152.     //    Build the AFM file
  1153.     //
  1154.     [self BuildAFMFileFrom: fontPtr Into: afmFile];
  1155.     //
  1156.     //    Build the ps font file
  1157.     //
  1158.     FontHeight = fontPtr->fRectHeight;
  1159.     //
  1160.     //    Write PS header comments
  1161.     //
  1162.     [DestFile   WriteComment: "!PS-Adobe-3.0"];
  1163.     [DestFile   WriteDSCCommentUsing: buffer WithFormat: "FontName: %s",  fontName];
  1164.     [DestFile   WriteDSCComment: "ConvertedFrom: (Macintosh bitmap font)"];
  1165.     timeString = ctime(¤tTime);
  1166.     timeString[24] = NullCharacter;    // Kill the final newline
  1167.     [DestFile   WriteDSCCommentUsing: buffer WithFormat: "CreationDate: (%s)",
  1168.                 timeString];
  1169.     [DestFile   WriteDSCCommentUsing: buffer
  1170.                 WithFormat: "Creator: (%s)", VERSIONSTRING];
  1171.     [DestFile   WriteDSCComment: "EndComments"];
  1172.     [DestFile   ForceNewLine];
  1173.     //
  1174.     //    Write some mini reference comments.
  1175.     //
  1176.     [DestFile      WriteComment:
  1177.                 "\tSome handy references (in orig. mac-bitmap coord system)"];
  1178.     [DestFile      WriteCommentUsing: buffer
  1179.                 WithFormat: "\tTotal Font Height is: %d", FontHeight];
  1180.     [DestFile      WriteCommentUsing: buffer
  1181.                 WithFormat: "\tFont Ascent is: %d", fontPtr->ascent];
  1182.     [DestFile      WriteCommentUsing: buffer
  1183.                 WithFormat: "\tFont Decent is: %d", fontPtr->descent];
  1184.     [DestFile      WriteComment:
  1185.             "\tNote: that the numbers in the char definitions are:"];
  1186.     [DestFile      WriteComment:
  1187.         "\t\twidth of character in bits/pixels"];
  1188.     [DestFile      WriteComment:
  1189.         "\t\toffset to start drawing from the char origin"];
  1190.     [DestFile   ForceNewLine];
  1191.     [DestFile   WritePSLineUsing: buffer WithFormat: "/%s 8 dict begin", fontName];
  1192.     [DestFile   ForceNewLine];
  1193.     //
  1194.     //    Define the font type and font matrix
  1195.     //
  1196.     [DestFile   WritePSLine: "/FontType 3 def"];
  1197.     [DestFile   WritePSLine: "/FontMatrix [0.001 0 0 0.001 0 0] def"];
  1198.     [DestFile   WritePSLineUsing: buffer  WithFormat: "/FontBBox [0 %.3f %.3f %.3f] def",
  1199.                 (fontPtr->descent * -1) * conversionFactor,
  1200.                 fontPtr->fRectWidth * conversionFactor,
  1201.                 fontPtr->ascent * conversionFactor];
  1202.     //
  1203.     //    Write the encoding array.
  1204.     //
  1205.     [DestFile   WriteText: "/Encoding ["];
  1206.     for (index = 0; index < 256; index++)
  1207.     {
  1208.         //
  1209.         //    93.03.14    Added code to support both NSEncoding and NS encoding vectors
  1210.         //
  1211.         if (UseNSEncoding == NO)
  1212.             [DestFile   WriteTextUsing: buffer WithFormat:" /%s",
  1213.                         EncodingVector[index]];
  1214.         else
  1215.             [DestFile   WriteTextUsing: buffer WithFormat:" /%s",
  1216.                         NSEncodingVector[index]];
  1217.     }
  1218.     [DestFile   WriteTextLine: "] def"];
  1219.     //
  1220.     //    Write the BuildGlyph procedure.   (I agree.  ICKY)
  1221.     //
  1222.     [DestFile   WritePSLine: "/BuildGlyph {"];
  1223.     [DestFile   WritePSLine: "    exch /CharProcs get exch"];
  1224.     [DestFile   WritePSLine: "    2 copy known not {pop /.notdef} if"];
  1225.     [DestFile   WritePSLine: "    get exec"];
  1226.     [DestFile   WritePSLine: "    /charimage exch def"];
  1227.     [DestFile   WriteTextUsing: buffer WithFormat: "\t/charoffset exch %.3f mul  def\n",
  1228.         conversionFactor];
  1229.     [DestFile   WriteTextUsing: buffer WithFormat: "\t/charwidth exch %.3f mul  def\n",
  1230.         conversionFactor];    
  1231.     [DestFile   WritePSLine: "    /bitwidth exch def"];
  1232.     [DestFile   WriteTextUsing: buffer WithFormat: "\tcharoffset 0  translate\n"];    [DestFile   WriteTextUsing: buffer WithFormat: "\tcharwidth 0\n\t0 %.3f %.3f  %.3f\n",
  1233.                 (fontPtr->descent * -1) * conversionFactor,
  1234.                 fontPtr->fRectWidth * conversionFactor,
  1235.                 fontPtr->ascent * conversionFactor];
  1236.     [DestFile   WriteTextUsing: buffer
  1237.         WithFormat: "\tsetcachedevice\n\tbitwidth %d true\n", FontHeight];
  1238.     [DestFile   WriteTextUsing: buffer WithFormat: "\t[%.3f 0 0 -%.3f 0 %d]\n",
  1239.                 FontHeight / 1000.0, FontHeight / 1000.0, fontPtr->ascent];
  1240.     [DestFile   WritePSLine: "\tcharimage"];
  1241.     [DestFile   WritePSLine: "\t imagemask"];
  1242.     [DestFile   WritePSLine: "} bind def"];
  1243.     [DestFile   WritePSLine: "/BuildChar {"];
  1244.     [DestFile   WritePSLine: "1 index /Encoding get exch get"];
  1245.     [DestFile   WritePSLine: "1 index /BuildGlyph get exec"];
  1246.     [DestFile   WritePSLine: "} bind def"];
  1247.     //
  1248.     //    Begin definition of the individual character procedures.
  1249.     //            (+1+1 is for 'fencepost' and undefined character)
  1250.     //
  1251.     [DestFile   WritePSLineUsing: buffer WithFormat: "/CharProcs %d  dict def",
  1252.                 fontPtr->lastChar-fontPtr->firstChar+1+1];
  1253.     [DestFile   WritePSLine: "CharProcs begin"];
  1254.  
  1255.     RowWords = fontPtr->rowWords;
  1256.     FontImage = &(fontPtr->ImageAndTables);
  1257.     LocationTable = (INTEGER*) ((FontHeight*RowWords*2) + FontImage);
  1258.     OffsetWidthTable = (OWEntry*)  (&(fontPtr->owTLoc) + fontPtr->owTLoc);
  1259.     destLine = NewByteString(RowWords*2);
  1260.  
  1261.     for (thechar = fontPtr->firstChar; thechar <= (fontPtr->lastChar+1);  thechar++)
  1262.     {
  1263.         //
  1264.         //    give the manager a crude idea of how far done we are (note we don't give
  1265.         //    %'s for the afm part, and this isn't accurate since we usually don't have
  1266.         //    all256 chars)
  1267.         //
  1268.         if ( [myManager   respondsTo:@selector(SetPercentageDone:)] ) 
  1269.             [myManager   SetPercentageDone: thechar / 2.56];
  1270.  
  1271.         index = thechar -  fontPtr->firstChar;
  1272.         //
  1273.         //    If there is data for this character (offset and width aren't -1), then extract it.
  1274.         //
  1275.         if ( ( OffsetWidthTable[index].offset != -1) && ( OffsetWidthTable[index].width != -1))
  1276.         {
  1277.             //
  1278.             //    Get the name for the character, and write it out.
  1279.             //
  1280.             if (thechar == fontPtr->lastChar+1)
  1281.                 [DestFile   WritePSLineUsing: buffer WithFormat: "/%s {", ".notdef "];
  1282.             else
  1283.             {
  1284.                 //
  1285.                 //    93.03.14    We do NOT want to write out NS encoding names here, since
  1286.                 //            no matter how you set up your references, the data that we
  1287.                 //            are extracting is comming out in a Mac encoding order
  1288.                 //
  1289.                 [DestFile   WritePSLineUsing: buffer
  1290.                     WithFormat: "/%s {", EncodingVector[thechar]];
  1291.             }
  1292.             //
  1293.             //    Prepare to extract the bit image by locating the first and
  1294.             //    last bit of the lines of pixels
  1295.             //
  1296.             startBit = LocationTable[index];
  1297.             endBit = LocationTable[index+1];
  1298.             imageWidth = endBit-startBit;
  1299.             //
  1300.             //    
  1301.             //
  1302.             [DestFile   WritePSLineUsing: (CString) buffer WithFormat:"\t%d", imageWidth];
  1303.             [DestFile   WritePSLineUsing: buffer WithFormat: "\t%d",
  1304.                         OffsetWidthTable[index].width];
  1305.             [DestFile   WritePSLineUsing: buffer WithFormat: "\t%d",
  1306.                         fontPtr->kernMax + OffsetWidthTable[index].offset];
  1307.             if (imageWidth <= 0)
  1308.             {
  1309.                 [DestFile   WritePSLine: "{<>}"];
  1310.             }
  1311.             else
  1312.             {
  1313.                 [DestFile   WritePSLine: "{<"];
  1314.                 //
  1315.                 //    Extract the bit image for each character
  1316.                 //    93.01.05    djb    Added check on imageWidth so we would not write out
  1317.                 //    empty lines.
  1318.                 //
  1319.                 for (line = 0; line < FontHeight; line ++)
  1320.                 {
  1321.                     RasterLine = &(FontImage[line*RowWords*2]);
  1322.                     [self   Copy: imageWidth BitsAtOffset: startBit
  1323.                         From: RasterLine Into: destLine];
  1324.                     [DestFile       Write: [self GetPositiveIntegerFrom: SECOND_RESULT] 
  1325.                         BytesOfHexDataFrom: destLine];
  1326.                 }
  1327.                 [DestFile   WritePSLine: ">}"];
  1328.             }
  1329.             [DestFile   WritePSLine: "} bind def"];
  1330.         }
  1331.     }
  1332.     [DestFile   WritePSLine: "end"];
  1333.     [DestFile   ForceNewLine];
  1334.     [DestFile   WritePSLine: "currentdict"];
  1335.     [DestFile   WritePSLine: "end"];
  1336.     [DestFile   WritePSLine: "definefont pop"];
  1337.  
  1338.     FreeByteString(destLine);
  1339.     FreeByteString((ByteString) fontPtr);
  1340.     FreeCString(tempString);
  1341.     FreeCString(buffer);
  1342.     //
  1343.     //    93.01.10    djb    Remove the stored name if there is one, so we don't re-use it next
  1344.     //                time.
  1345.     //
  1346.     if (StoredName != NullCString)
  1347.     {
  1348.         FreeCString(StoredName);
  1349.         StoredName = NullCString;
  1350.     }
  1351.     return self;
  1352. }
  1353.  
  1354.  
  1355. //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  1356. //    Method:        SetFullNameTo:
  1357. //    Parameters:    A string that will be used as the font's name
  1358. //    Returns:     self
  1359. //    Stores:        none
  1360. //    Description:
  1361. //        This is added to the font converter on 93.01.10... that is, just as I'm doing my
  1362. //        final pre-beta testing.  I found that one could say: convert this font:
  1363. //                myfont(it's way cool).font
  1364. //        and this would dutifully create a font with the name myfont(it's way cool)
  1365. //        but this name makes PS get ill due to special characters.  Yet, one wants this
  1366. //        name to appear in the font menu.  So, this name is passed to this method which
  1367. //        stores it for storage in the afm file in the right places, while the rest of the
  1368. //        converter uses a name like  myfontit'swaycool.  In any case, this just makes a
  1369. //        copy of the string.  It's up to the conversion routine to deallocate it when it's done
  1370. //        so it doesn't get confused.
  1371. //    Bugs:
  1372. //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  1373. -SetFullNameTo: (ConstCString) filename
  1374. {
  1375.     if (StoredName != NullCString)
  1376.         FreeCString(StoredName);
  1377.     StoredName = NewCString(strlen(filename));
  1378.     strcpy(StoredName, filename);
  1379.     return self;
  1380. }
  1381.  
  1382.  
  1383. //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  1384. //    Method:        GetFontRecordFrom:
  1385. //    Parameters:    the file to read a Mac font record structure from
  1386. //    Returns:     a pointer to a font record (caller must dispose of the memory)
  1387. //    Stores:        none
  1388. //    Description:
  1389. //        This routine reads in a big-endian Macintosh font record from.  Since this may
  1390. //        be running on little endian (or other? =) machines, this routine then builds a
  1391. //        new structure for the endianness that is currently in use.
  1392. //        This is redundant work for Black hardware, but what the heck.  
  1393. //    History:
  1394. //        93.08.01    djb    Created, thus insulating the rest of the code from endian concerns
  1395. //                    in the source files.
  1396. //        93.08.15    djb    Argh!  I need to be casting the results!!!
  1397. //        93.11.05    djb    Added code to do the endian flip of the location table.
  1398. //    Bugs:
  1399. //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  1400. - (FontRecPtr) GetFontRecordWithLength: (PositiveInteger) fontLength From: SourceFile
  1401. {
  1402.     FontRecPtr    sourceFontRec;
  1403.     FontRecPtr    destFontRec;
  1404.     Integer        index;
  1405.     INTEGER    *LocationTable;
  1406.     INTEGER    *DestLocationTable;
  1407.     INTEGER    FontBitmapSize;
  1408.  
  1409.     sourceFontRec = (FontRecPtr) NewByteString(fontLength);
  1410.     destFontRec = (FontRecPtr) NewByteString(fontLength);
  1411.     
  1412.     [SourceFile   Read: fontLength BytesInto: (ByteString) sourceFontRec];
  1413.     //
  1414.     //    Copy the source font record to the destination record.  This moves the font bitmaps
  1415.     //    and other stuff which we have no plans to copy.
  1416.     //
  1417.     memcpy(destFontRec, sourceFontRec, fontLength);
  1418.     //
  1419.     //    Now, swap all the INTEGERS (2 byte integers) from big endian to whwatever
  1420.     //    the local endianness is.
  1421.     //
  1422.     destFontRec->fontType = (INTEGER) NXSwapBigShortToHost(sourceFontRec->fontType);
  1423.     destFontRec->firstChar = (INTEGER) NXSwapBigShortToHost(sourceFontRec->firstChar);
  1424.     destFontRec->lastChar = (INTEGER) NXSwapBigShortToHost(sourceFontRec->lastChar);
  1425.     destFontRec->widMax = (INTEGER) NXSwapBigShortToHost(sourceFontRec->widMax);
  1426.     destFontRec->kernMax = (INTEGER) NXSwapBigShortToHost(sourceFontRec->kernMax);
  1427.     destFontRec->nDescent = (INTEGER) NXSwapBigShortToHost(sourceFontRec->nDescent);
  1428.     destFontRec->fRectWidth = (INTEGER) NXSwapBigShortToHost(sourceFontRec->fRectWidth);
  1429.     destFontRec->fRectHeight = (INTEGER) NXSwapBigShortToHost(sourceFontRec->fRectHeight);
  1430.     destFontRec->owTLoc = (INTEGER) NXSwapBigShortToHost(sourceFontRec->owTLoc);
  1431.     destFontRec->ascent = (INTEGER) NXSwapBigShortToHost(sourceFontRec->ascent);
  1432.     destFontRec->descent = (INTEGER) NXSwapBigShortToHost(sourceFontRec->descent);
  1433.     destFontRec->leading = (INTEGER) NXSwapBigShortToHost(sourceFontRec->leading);
  1434.     destFontRec->rowWords = (INTEGER) NXSwapBigShortToHost(sourceFontRec->rowWords);
  1435.     //
  1436.     //    Flip the endianness, if needed, of the location table.  The +3 in the for loop is because
  1437.     //    +1 to compensate for the last-first subtraction to get the number of chars, +1 for the unknown
  1438.     //    character at the end of the font, and +1 for the final location, since one needs a trailing
  1439.     //    location to mark where the last character ends.
  1440.     //
  1441.     FontBitmapSize = ((destFontRec->fRectHeight * destFontRec->rowWords) * 2);
  1442.     LocationTable = (INTEGER*) (FontBitmapSize + (&(sourceFontRec->ImageAndTables)));
  1443.     DestLocationTable = (INTEGER*) (FontBitmapSize + (&(destFontRec->ImageAndTables)));
  1444.     for (index = 0; index <= ((destFontRec->lastChar - destFontRec->firstChar)+3);  index++)
  1445.         DestLocationTable[index] = (INTEGER) NXSwapBigShortToHost(LocationTable[index]);
  1446.     //
  1447.     //    dispose of the source one, and return the destination.
  1448.     //
  1449.     FreeByteString((ByteString)sourceFontRec);
  1450.     return destFontRec;
  1451. }
  1452.  
  1453.  
  1454.  
  1455.  
  1456.  
  1457.  
  1458. @end;
  1459.